dojo.provide("apt.CalendarComponent");
dojo.require("apt.CalendarDay");
dojo.require("dijit._WidgetBase");
dojo.require("dijit.WidgetSet");
dojo.require("dijit._TemplatedMixin");

dojo.declare("apt.CalendarComponent", [dijit._WidgetBase, dijit._TemplatedMixin], {
  templateString: dojo.cache('apt.templates', 'CalendarComponent.html'),
  widgetsInTemplate:  true,
  days:               [],
  startDate:          "",
  daysShowing:        "",
  leftOffsetInDays:   7,
  quotient:           3,
  displayArea:        { },
  parent:             '',
  dragHandle:         {},
  scrollThrottle:     '',
  scrollEventHandler: '',
  
  constructor: function(data){		
    this.inherited(arguments);
    dojo.safeMixin(this, data);
    this.daysShowing = this.parent.daysShowing;
    this.leftOffsetInDays = parseInt((this.quotient*this.daysShowing-this.daysShowing)/2);
  },
      
  postCreate: function() {
    dojo.connect(this.containerNode, 'onmousedown', this, this.dragStart);    
  },
    
  startup: function(){	
    this.generateDays();
  },
  
  dragStart: function(event){
    this.dragHandle.moveHandler = dojo.connect(document, 'onmousemove', this, this.dragMove);
    this.dragHandle.endHandler = dojo.connect(document, 'onmouseup', this, this.dragEnd);
    this.dragHandle.x = event.clientX;
    dojo.style(document.body, 'cursor', 'move');
    dojo.style(document.body, 'cursor', '-webkit-grab');
  },
  
  dragMove: function(event){
    var xdiff = event.clientX - this.dragHandle.x;
    this.dragHandle.x = event.clientX;
    this.domNode.scrollLeft = this.domNode.scrollLeft - xdiff; 
  },

  dragEnd: function(event){
    dojo.disconnect(this.dragHandle.moveHandler);
    dojo.disconnect(this.dragHandle.endHandler);
    dojo.style(document.body, 'cursor', 'default');
    if (Math.abs(this.dragHandle.original_x - event.clientX) > 4){
      dojo.stopEvent(event);
    };
  },
  
  generateDays: function(){
    if (this.scrollEventHandler !== ''){
      dojo.disconnect(this.scrollEventHandler);
      this.scrollEventHandler = '';
    }
    
    for (var i=0; i < this.days.length; i++) {
      this.days[i].delete();
    };
    this.days = [];
    
    var dayWidth = dojo.position(this.containerNode).w / this.daysShowing;

    //Add empty days as padding around the view. 
    for (var i=0; i < this.daysShowing * this.quotient; i++) {
			var renderBoolean = (i >= this.leftOffsetInDays && i < this.leftOffsetInDays+this.daysShowing ) ? true : false;
      var day = new apt.CalendarDay({
        date: this.getTomorrow(this.startDate, i-this.leftOffsetInDays),
        parent: this,
				brain: this.parent,
				isShowing: renderBoolean,
        width: dayWidth
      });
      this.days.push(day);      
      day.placeAt(this.containerNode);
      day.startup();
    };
    this.scrollEventHandler = dojo.connect(this.domNode, 'onscroll', this, this.scrollHandlerThrottled);    
  },
	
  regenerateDays: function(value){
    if (value === "today"){
      var today = new Date();
      value = Math.round((today - this.startDate) / 86400000) -1;
    }
    value = parseInt(value);
    
    if (value < 0){
      if (value >= this.getMaximumLeftOffsetInDaysLeft()){
        var offset = value * dojo.position(this.domNode).w / this.daysShowing;
        this.domNode.scrollLeft += offset;
        this.scrollHandler();
      } else {
        this.startDate.setDate(this.startDate.getDate() + value);
        this.generateDays();
      }
    } else if (value > 0) {
      if (value <= this.getMaximumLeftOffsetInDaysRight()){
        var offset = value * dojo.position(this.domNode).w / this.daysShowing;
        this.domNode.scrollLeft += offset;
        this.scrollHandler();
      } else {
        this.startDate.setDate(this.startDate.getDate() + value);
        this.generateDays();
      }
    }
  },

	resizeCalendarComponentHeight: function(){
		var cont = dojo.marginBox(this.containerNode);
		
    dojo.style(this.containerNode, 'height', 'auto');
		if (cont.h + cont.t < document.height) {
			dojo.style(this.containerNode, 'height', document.height - cont.t + 44 + 'px');
		}
	},
  
	resizeCalendarComponent: function(){
    this.resizeCalendarComponentHeight();  
    
		var width = 0;
    for (var i=0; i < this.days.length; i++) {
      width += dojo.position(this.days[i].domNode).w;
    };
		
    dojo.style(this.containerNode, 'width', width + "px");

		var offset = width / this.days.length * this.leftOffsetInDays;
		this.domNode.scrollLeft = offset; 
		this.setLeftOffsetInDays();
    
	},

  scrollHandlerThrottled: function(){
    clearTimeout(this.scrollThrottle);    
    this.scrollThrottle = setTimeout(dojo.hitch(this, this.scrollHandler), 100);
  },

  scrollHandler: function(){
    var days = this.daysShowing * this.quotient;
    
    var pos = dojo.position(this.domNode);    
    var left = this.domNode.scrollLeft;
    var right = pos.x + pos.w;
    var displayWidth = pos.w;
    var dayWidth = displayWidth/this.daysShowing;
    var firstIndexShowing = parseInt(left/dayWidth);
    var lastIndexShowing = parseInt(right/dayWidth);

    var paddingInDays = parseInt((days - this.daysShowing)/2);
    
    var howMany = paddingInDays-firstIndexShowing;
    
    if (howMany > 0) {
      this.shiftLeft(howMany);
    } else if (howMany < 0) {
      this.shiftRight(Math.abs(howMany));
    }
    
    this.setLeftOffsetInDays();
  },
  
  shiftLeft: function(count){
    if (typeof count == 'undefined'){
      count = 1;
    }
    
    this.startDate.setDate(this.startDate.getDate() - count);
    this.showVisible(-count);
    
    var newDays = [];
    var dayLength = dojo.position(this.domNode).w / this.daysShowing;
    
    for (var i = count; i >= 1; i--){      
      var day = new apt.CalendarDay({
        date: this.getTomorrow(this.days[0].date, -i),
        parent: this,
  			brain: this.parent,
  			isShowing: false,
        width: dayLength
      });
      newDays.push(day);
    };
    
    for (var i = newDays.length - 1; i >= 0; i--){
      newDays[i].placeAt(this.containerNode, 'first');
      newDays[i].startup();
    };

    this.domNode.scrollLeft += dayLength*count;    

    for (var i = newDays.length - 1; i >= 0; i--){      
      var drop = this.days[this.days.length-1];
      this.days.unshift(newDays[i]);
      this.days.splice(-1, 1);
      drop.delete();      
    };
    
	},

	shiftRight: function(count){ 
    if (typeof count == 'undefined'){
      count = 1;
    }
    
    this.startDate.setDate(this.startDate.getDate() + count);
    this.showVisible(count);
    
    var newDays = [];
    var dayLength = dojo.position(this.domNode).w / this.daysShowing;
    
    for (var i = count; i >= 1; i--){
      var day = new apt.CalendarDay({
        date: this.getTomorrow(this.days[this.days.length - 1].date, i),
        parent: this,
  			brain: this.parent,
  			isShowing: false,
        width: dayLength
      });
      newDays.push(day);
    };
    
    for (var i = newDays.length - 1; i >= 0; i--){
      newDays[i].placeAt(this.containerNode, 'last');
    };

    this.domNode.scrollLeft -= dayLength*count;    
    
    for (var i = newDays.length - 1; i >= 0; i--){
      newDays[i].startup();
      
      var drop = this.days[0];
      this.days.push(newDays[i]);
      this.days.splice(0, 1);
      drop.delete();
    };
	},
  
  showVisible: function( offset ){
    var daylen = this.daysShowing * this.quotient;
    var daymax = this.days.length;
    var padding = parseInt((this.daysShowing * this.quotient - this.daysShowing)/2) + offset;
    for (var i=0; i < daylen && i < daymax; i++) {
      if (i > padding - 1 && i < padding + this.daysShowing + 1){
        this.days[i].setShowing();        
      } else if (i < padding - this.daysShowing/2 || i > padding + this.daysShowing/2 ) {
        this.days[i].setIsHidden();
      }
    };
  },
	
	getPrev: function(){
    return this.days.length/3 - 1;
	},

	getNext: function(){
    return this.days.length/3 * 2;
	},
	
	loadDataForDay: function(index){
    this.days[index].setShowing();
	},
	
  getMaximumLeftOffsetInDaysLeft: function(){
    var days = this.daysShowing * this.quotient;
    var padding = parseInt((days - this.daysShowing)/2);
    return -padding;
  },

  getMaximumLeftOffsetInDaysRight: function(){
    var days = this.daysShowing * this.quotient;
    var padding = parseInt((days - this.daysShowing)/2);
    return days - padding;
  },
  	
	setLeftOffsetInDays: function() {
		this.leftOffsetInDays = this.domNode.scrollLeft / dojo.position(this.domNode).w * this.daysShowing;
	},
  
  getTomorrow: function(d,offset) {
    return new Date(d.getTime() + (86400000*offset));
  },
  
  resize: function(){		
		// console.log(this.parent.contentContainer.scrollLeft);
    var viewPortSize = dojo.position(this.domNode).w;
    this.daysShowing = this.parent.daysShowing;		
    
    for (var i=0; i < this.days.length; i++) {
      this.days[i].resize(viewPortSize);
    };
		
		this.resizeCalendarComponent();		
  }
});

